#ifndef _CDN_SERVER_H
#define _CDN_SERVER_H

#include <iostream>
#include <fstream>
#include <string>
#include <vector>
#include <stdint.h>
#include <map>
#include"pthread.h"

#include "HttpParser.h"
#include "NetworkFw.h"
#include "Logger.h"
#include "FileManager.h"
#include "server-addr-config.h"

using namespace std;

class CdnNode;
extern FileManager file_manager;

enum CdnSessionState {
    CDN_SESSION_STATE_IDLE,
    CDN_SESSION_STATE_BUSY,
};

struct CdnSession: public Session {
    int state;
    string request;
    CdnDiskStream *dstream;
    fw_file_size_t len;
    fw_file_size_t bytes_sent;
    CdnSession (SockNode *node): 
        Session(node), state(CDN_SESSION_STATE_IDLE), 
        request("\0"), dstream(0) {};

    virtual ~CdnSession() {
        if (dstream) {
            file_manager.CloseDiskStream(dstream);
        }
    }
    friend class CdnNode;
};

class CdnNode: public AppNode {
    public:
	CdnNode() {
            networker.StartListening(TNMC_CDN_SERVER_TCP_PORT);
        }
	~CdnNode() {};
        virtual void HandleRecvMsg(FwAppMsg *msg);
        virtual void HandleSendMsg(FwAppMsg *msg);
    protected:
        virtual Session *ConstructSession(SockNode *sock_node) { 
            return (new CdnSession(sock_node)); 
        }
        //private methods
        void GetLocalTransferPort(int sockfd, string &transfer_port_str);
        void ProcessLocatingRequest(CdnSession *session);
        void ProcessTransferRequest(CdnSession *session);
        friend class FileManager;
};


#endif

